package com.chery.foxlogrecord.demo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chery.foxlogrecord.core.annotation.LogRecord;
import com.chery.foxlogrecord.core.annotation.LogRecordModel;
import com.chery.foxlogrecord.core.enums.LogOperate;
import com.chery.foxlogrecord.demo.entity.User;
import com.chery.foxlogrecord.demo.entity.UserFamily;
import com.chery.foxlogrecord.demo.enums.LogModule;
import com.chery.foxlogrecord.demo.mapper.UserMapper;
import com.chery.foxlogrecord.demo.pojo.dto.Address;
import com.chery.foxlogrecord.demo.pojo.dto.UserDto;
import com.chery.foxlogrecord.demo.pojo.dto.UserPageDto;
import com.chery.foxlogrecord.demo.service.UserFamilyService;
import com.chery.foxlogrecord.demo.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserFamilyService userFamilyService;

    @LogRecord(key = "#result.id",
            module = LogModule.Type.USER,
            desc = "新增用户",
            operateType = LogOperate.Type.SAVE)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserDto insert(@LogRecordModel("userDto") UserDto userDto) {
        User user = BeanUtil.toBean(userDto, User.class);
        user.setAddress(JSON.toJSONString(userDto.getAddress()));
        this.save(user);
        userDto.setId(user.getId());
        if (CollectionUtil.isNotEmpty(userDto.getUserFamilyList())) {
            userDto.getUserFamilyList().forEach(userFamily -> {
                userFamily.setUserId(user.getId());
            });
            userFamilyService.saveBatch(userDto.getUserFamilyList());
        }
        return userDto;
    }

    @LogRecord(key = "#userDto.id",
            module = LogModule.Type.USER,
            desc = "更新用户",
            operateType = LogOperate.Type.UPDATE,
            method = "@userServiceImpl.findById(#root)")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserDto edit(@LogRecordModel("userDto") UserDto userDto) {
        User user = BeanUtil.toBean(userDto, User.class);
        user.setAddress(JSON.toJSONString(userDto.getAddress()));
        this.updateById(user);
        if (CollectionUtil.isNotEmpty(userDto.getUserFamilyList())) {
            userFamilyService.lambdaUpdate().eq(UserFamily::getUserId, userDto.getId()).set(UserFamily::getDeleted, true).update();
            userDto.getUserFamilyList().forEach(userFamily -> {
                userFamily.setUserId(user.getId());
            });
            userFamilyService.saveBatch(userDto.getUserFamilyList());
        }
        return userDto;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Long> idList) {
        for (Long id : idList) {
            this.delete(id);
        }
    }

    @Override
    public UserDto findById(Long id) {
        User user = this.lambdaQuery().eq(User::getId, id).one();
        UserDto userDto = BeanUtil.toBean(user, UserDto.class, CopyOptions.create().setIgnoreProperties(User::getAddress));
        if (StrUtil.isNotBlank(user.getAddress())) {
            userDto.setAddress(JSON.parseObject(user.getAddress(), Address.class));
        }
        if (ObjectUtil.isNotNull(user)) {
            List<UserFamily> list = userFamilyService.lambdaQuery().eq(UserFamily::getUserId, user.getId()).list();
            userDto.setUserFamilyList(list);
        }
        return userDto;
    }

    @Override
    public Page<User> pageList(UserPageDto userPageDto) {
        Page<User> page = new Page<User>(userPageDto.getPageCurrent(), userPageDto.getPageSize());
        return this.lambdaQuery().eq(StrUtil.isNotEmpty(userPageDto.getUsername()), User::getUsername, userPageDto.getUsername()).page(page);
    }

}
